package com.example.netty.netty.dubboRPC.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.lang.reflect.Proxy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: 江涛
 * @CreateTime: 2022-09-22  21:39
 * @Description:
 */
public class NettyClient {
    //创建线程池
    private static ExecutorService executor = Executors.newFixedThreadPool(10);

    private static NettyClientHandler handler;

    /**
     * 创建代理对象
     * @param serviceClass 要调用那个接口
     * @param providerName 校验信息（也就是HelloServer#）
     * @return
     */
    public Object getBean(final Class<?> serviceClass, String providerName) {
        //直接返回一个代理对象,类加载器、接口、代理方法
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class<?>[]{serviceClass},(proxy,method,args)->{
                    System.out.println("执行代理方法");
                    if (handler == null) {
                        initClient();
                    }
                    handler.setParam(providerName+args[0]);
                    return executor.submit(handler).get();
                });
    }

    private static void initClient() throws InterruptedException {
        NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventExecutors)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true) //不阻塞
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            handler = new NettyClientHandler();
                            ch.pipeline().addLast(new StringDecoder())
                                    .addLast(new StringEncoder())
                                    .addLast(handler);
                        }
                    });
            System.out.println("客户端启动成功");
            ChannelFuture sync = bootstrap.connect("127.0.0.1",7000).sync();
            sync.channel().closeFuture();
        }finally {
            //因为finally中的一定会执行，我们一般写的话因为都是在main函数里，
            // 程序会卡在 future.channel().closeFuture().sync()，执行不到finally里面的代码，
            // 但是最后这个例子并不是在main函数里，不能让他阻塞在这里所以就没有加上sync()，
            // 则finally一定会执行，这就相当于还没执行完就把连接关了，所以会出问题
//            eventExecutors.shutdownGracefully();
        }
    }
}
